--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
sbapp/pyogg/opus_file.py f8b3e3760b831745cf10d97aeae64e9c00a136a9 (f8b3e376) Text, 3.21 KB
Tff7b72import T7ee787ctypes
Tff7b72from T7ee787. Tff7b72import Te6edf3ogg
Tff7b72from T7ee787. Tff7b72import Te6edf3opus
Tff7b72from T7ee787.T7ee787pyogg_error Tff7b72import Te6edf3PyOggError
Tff7b72from T7ee787.T7ee787audio_file Tff7b72import Te6edf3AudioFile
Tff7b72class T56d364OpusFileTb4b4b4(Te6edf3AudioFileTb4b4b4)Tb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e# Open the file
Te6edf3error Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffc_intTb4b4b4(Tb4b4b4)
Te6edf3of Tff7b72= Te6edf3opusTff7b72.Td2a8ffop_open_fileTb4b4b4(
Te6edf3oggTff7b72.Td2a8ffto_char_pTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffpointerTb4b4b4(Te6edf3errorTb4b4b4)
Tb4b4b4)
T8b949e# Check for errors
Tff7b72if Te6edf3errorTff7b72.Td2a8ffvalue Tff7b72!= T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Tb4b4b4(Ta5d6ff"Ta5d6ffFile Ta5d6ff'Tffd700{}Ta5d6ff'Ta5d6ff couldnTa5d6ff'Ta5d6fft be opened or doesnTa5d6ff'Ta5d6fft exist. Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffError code: Tffd700{}Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3errorTff7b72.Td2a8ffvalueTb4b4b4)
Tb4b4b4)
T8b949e# Extract the number of channels in the newly opened file
T8b949e#: Number of channels in audio file.
Tff7b72selfTff7b72.Td2a8ffchannels Tff7b72= Te6edf3opusTff7b72.Td2a8ffop_channel_countTb4b4b4(Te6edf3ofTb4b4b4, Tff7b72-T79c0ff1Tb4b4b4)
T8b949e# Allocate sufficient memory to store the entire PCM
Te6edf3pcm_size Tff7b72= Te6edf3opusTff7b72.Td2a8ffop_pcm_totalTb4b4b4(Te6edf3ofTb4b4b4, Tff7b72-T79c0ff1Tb4b4b4)
Te6edf3Buf Tff7b72= Te6edf3opusTff7b72.Td2a8ffopus_int16Tff7b72*Tb4b4b4(Te6edf3pcm_sizeTff7b72*Tff7b72selfTff7b72.Td2a8ffchannelsTb4b4b4)
Te6edf3buf Tff7b72= Te6edf3BufTb4b4b4(Tb4b4b4)
T8b949e# Create a pointer to the newly allocated memory. It
T8b949e# seems we can only do pointer arithmetic on void
T8b949e# pointers. See
T8b949e# https://mattgwwalker.wordpress.com/2020/05/30/pointer-manipulation-in-python/
Te6edf3buf_ptr Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffcastTb4b4b4(
Te6edf3ctypesTff7b72.Td2a8ffpointerTb4b4b4(Te6edf3bufTb4b4b4)Tb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffc_void_p
Tb4b4b4)
Tff7b72assert Te6edf3buf_ptrTff7b72.Td2a8ffvalue Tff7b72is Tff7b72not Tff7b72None T8b949e# for mypy
Te6edf3buf_ptr_zero Tff7b72= Te6edf3buf_ptrTff7b72.Td2a8ffvalue
T8b949e#: Bytes per sample
Tff7b72selfTff7b72.Td2a8ffbytes_per_sample Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffsizeofTb4b4b4(Te6edf3opusTff7b72.Td2a8ffopus_int16Tb4b4b4)
T8b949e# Read through the entire file, copying the PCM into the
T8b949e# buffer
Te6edf3samples Tff7b72= T79c0ff0
Tff7b72while Tff7b72TrueTb4b4b4:
T8b949e# Calculate remaining buffer size
Te6edf3remaining_buffer Tff7b72= Tb4b4b4(
Tffa657lenTb4b4b4(Te6edf3bufTb4b4b4) T8b949e# int
Tff7b72- Tb4b4b4(Te6edf3buf_ptrTff7b72.Td2a8ffvalue
Tff7b72- Te6edf3buf_ptr_zeroTb4b4b4) Tff7b72/Tff7b72/ Tff7b72selfTff7b72.Td2a8ffbytes_per_sample
Tb4b4b4)
T8b949e# Convert buffer pointer to the desired type
Te6edf3ptr Tff7b72= Te6edf3ctypesTff7b72.Td2a8ffcastTb4b4b4(
Te6edf3buf_ptrTb4b4b4,
Te6edf3ctypesTff7b72.Td2a8ffPOINTERTb4b4b4(Te6edf3opusTff7b72.Td2a8ffopus_int16Tb4b4b4)
Tb4b4b4)
T8b949e# Read the next section of PCM
Te6edf3ns Tff7b72= Te6edf3opusTff7b72.Td2a8ffop_readTb4b4b4(
Te6edf3ofTb4b4b4,
Te6edf3ptrTb4b4b4,
Te6edf3remaining_bufferTb4b4b4,
Te6edf3oggTff7b72.Td2a8ffc_int_pTb4b4b4(Tb4b4b4)
Tb4b4b4)
T8b949e# Check for errors
Tff7b72if Te6edf3nsTff7b72<T79c0ff0Tb4b4b4:
Tff7b72raise Te6edf3PyOggErrorTb4b4b4(
Ta5d6ff"Ta5d6ffError while reading OggOpus file. Ta5d6ff"Tff7b72+
Ta5d6ff"Ta5d6ffError code: Tffd700{}Ta5d6ff"Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3nsTb4b4b4)
Tb4b4b4)
T8b949e# Increment the pointer
Te6edf3buf_ptrTff7b72.Td2a8ffvalue Tff7b72+Tff7b72= Tb4b4b4(
Te6edf3ns
Tff7b72* Tff7b72selfTff7b72.Td2a8ffbytes_per_sample
Tff7b72* Tff7b72selfTff7b72.Td2a8ffchannels
Tb4b4b4)
Tff7b72assert Te6edf3buf_ptrTff7b72.Td2a8ffvalue Tff7b72is Tff7b72not Tff7b72None T8b949e# for mypy
Te6edf3samples Tff7b72+Tff7b72= Te6edf3ns
T8b949e# Check if we've finished
Tff7b72if Te6edf3nsTff7b72==T79c0ff0Tb4b4b4:
Tff7b72break
T8b949e# Close the open file
Te6edf3opusTff7b72.Td2a8ffop_freeTb4b4b4(Te6edf3ofTb4b4b4)
T8b949e# Opus files are always stored at 48k samples per second
T8b949e#: Number of samples per second (per channel). Always 48,000.
Tff7b72selfTff7b72.Td2a8fffrequency Tff7b72= T79c0ff48000
T8b949e# Cast buffer to a one-dimensional array of chars
T8b949e#: Raw PCM data from audio file.
Te6edf3CharBuffer Tff7b72= Tb4b4b4(
Te6edf3ctypesTff7b72.Td2a8ffc_byte
Tff7b72* Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffbytes_per_sample Tff7b72* Tff7b72selfTff7b72.Td2a8ffchannels Tff7b72* Te6edf3pcm_sizeTb4b4b4)
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffbuffer Tff7b72= Te6edf3CharBufferTff7b72.Td2a8fffrom_bufferTb4b4b4(Te6edf3bufTb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────